package com.celan.year2023.month02.day07;

import java.util.*;

public class Solution {
    public List<String> alertNames(String[] keyName, String[] keyTime) {
        int n = keyName.length;
        List<String> res = new ArrayList<>();
        HashMap<String, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            String name = keyName[i];
            int time = toTime(keyTime[i]);
            map.putIfAbsent(name, new ArrayList<>());
            map.get(name).add(time);
        }

        for (String name : map.keySet()) {
            List<Integer> times = map.get(name);
            Collections.sort(times);
            int size = times.size();
            if (size < 3) continue;
            for (int i = 2; i < size; i++) {
                int start = times.get(i - 2), end = times.get(i);
                if (end - start <= 60) {
                    res.add(name);
                    break;
                }
            }
        }

        Collections.sort(res);
        return res;
    }

    private int toTime(String s) {
        int hour = (s.charAt(0) - '0') * 10 + (s.charAt(1) - '0');
        int minutes = (s.charAt(3) - '0') * 10 + (s.charAt(4) - '0');
        return hour * 60 + minutes;
    }

    class TrieNode {
        String s;
        TrieNode[] tns = new TrieNode[26];
    }

    void insert(String s) {
        TrieNode p = root;
        for (int i = 0; i < s.length(); i++) {
            int u = s.charAt(i) - 'a';
            if (p.tns[u] == null) p.tns[u] = new TrieNode();
            p = p.tns[u];
        }
        p.s = s;
    }

    Set<String> set = new HashSet<>();
    char[][] board;
    int n, m;
    TrieNode root = new TrieNode();
    int[][] dirs = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    boolean[][] vis = new boolean[15][15];

    public List<String> findWords(char[][] _board, String[] words) {
        board = _board;
        m = board.length;
        n = board[0].length;
        for (String w : words) insert(w);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int u = board[i][j] - 'a';
                if (root.tns[u] != null) {
                    vis[i][j] = true;
                    dfs(i, j, root.tns[u]);
                    vis[i][j] = false;
                }
            }
        }
        List<String> ans = new ArrayList<>();
        for (String s : set) ans.add(s);
        return ans;
    }

    void dfs(int i, int j, TrieNode node) {
        if (node.s != null) set.add(node.s);
        for (int[] d : dirs) {
            int dx = i + d[0], dy = j + d[1];
            if (dx < 0 || dx >= m || dy < 0 || dy >= n) continue;
            if (vis[dx][dy]) continue;
            int u = board[dx][dy] - 'a';
            if (node.tns[u] != null) {
                vis[dx][dy] = true;
                dfs(dx, dy, node.tns[u]);
                vis[dx][dy] = false;
            }
        }
    }
}
